using System.Collections.Concurrent;
using Serilog;

namespace 后端服务.Services;

/// <summary>
/// SQL查询日志服务
/// </summary>
public class SqlLoggerService
{
    private readonly ConcurrentQueue<SqlLogEntry> _recentQueries = new();
    private readonly int _maxEntries;
    
    public SqlLoggerService(IConfiguration configuration)
    {
        _maxEntries = configuration.GetValue<int>("SqlLogger:MaxEntries", 100);
    }
    
    /// <summary>
    /// 记录SQL查询
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="parameters">参数</param>
    /// <param name="duration">执行时间(毫秒)</param>
    /// <param name="isSuccess">是否成功</param>
    /// <param name="error">错误信息</param>
    public void LogQuery(string sql, Dictionary<string, object>? parameters, long duration, bool isSuccess, string? error = null)
    {
        var entry = new SqlLogEntry
        {
            Timestamp = DateTime.UtcNow,
            Sql = sql,
            Parameters = parameters,
            DurationMs = duration,
            IsSuccess = isSuccess,
            Error = error
        };
        
        _recentQueries.Enqueue(entry);
        
        // 限制队列大小
        while (_recentQueries.Count > _maxEntries && _recentQueries.TryDequeue(out _)) { }
        
        // 记录到Serilog
        if (isSuccess)
        {
            Log.Information("SQL executed in {Duration}ms: {Sql}", duration, sql);
            if (parameters?.Count > 0)
            {
                Log.Information("Parameters: {@Parameters}", parameters);
            }
        }
        else
        {
            Log.Error("SQL error in {Duration}ms: {Sql}, Error: {Error}", duration, sql, error);
            if (parameters?.Count > 0)
            {
                Log.Error("Parameters: {@Parameters}", parameters);
            }
        }
    }
    
    /// <summary>
    /// 获取最近的查询记录
    /// </summary>
    /// <param name="count">要获取的记录数量</param>
    /// <param name="onlyErrors">是否只获取错误记录</param>
    /// <returns>查询记录列表</returns>
    public List<SqlLogEntry> GetRecentQueries(int count = 20, bool onlyErrors = false)
    {
        return _recentQueries
            .Where(q => !onlyErrors || !q.IsSuccess)
            .OrderByDescending(q => q.Timestamp)
            .Take(count)
            .ToList();
    }
}

/// <summary>
/// SQL日志条目
/// </summary>
public class SqlLogEntry
{
    public DateTime Timestamp { get; set; }
    public string Sql { get; set; } = string.Empty;
    public Dictionary<string, object>? Parameters { get; set; }
    public long DurationMs { get; set; }
    public bool IsSuccess { get; set; }
    public string? Error { get; set; }
}